package com.zy.utils.data

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import com.zy.utils.CanvasUtils.drawTextCenter
import android.view.MotionEvent

//默认方形
open class Point {

    companion object {
        const val ASS_INDEX = 9999
    }

    var originX //原始x坐标
            : Int
    var originY //原始Y坐标
            : Int
    var v //数据
            : String?

    @JvmField
    protected var per //长宽或者R
            : Float

    var d: Int
    var index: Int //下标
        protected set
    private var showIndex //下标
            = false
    private var circle //方形和圆形
            = false
    private var offX //偏移
            = 0f
    private var offY //偏移
            = 0f
    private var percentage = 1f //偏移百分比
    private var mark = false
    private var canMove = true
    private var type: Type = Type.DEFAULT
    private var backgroundColor: Int? = null

    //方向-[0,360]
    private var degrees: Float = 0F

    //箭头
    protected var arrowType: Int = 0

    //内容字体大小
    private var vTextSize: Int = 72


    //绘制背景的画笔
    private val backgroundPaint = Paint()

    init {
        //设置文本大小
        backgroundPaint.isAntiAlias = true
        backgroundPaint.color = Color.BLUE
    }

    constructor(builder: Builder) {
        originX = builder.originX
        originY = builder.originY
        v = builder.v
        per = builder.per
        d = builder.d
        index = builder.index
        showIndex = builder.showIndex
        circle = builder.circle
        canMove = builder.canMove
        type = builder.type
        backgroundColor = builder.backgroundColor
        degrees = builder.degrees
        arrowType = builder.arrowType
        vTextSize = builder.vTextSize
    }

    fun toBuilder(): Builder {
        return Builder().also {
            it.originX = this.originX
            it.originY = this.originY
            it.v = this.v
            it.per = this.per
            it.d = this.d
            it.index = this.index
            it.showIndex = this.showIndex
            it.circle = this.circle
            it.canMove = this.canMove
            // TODO:  可能为true,通过Gson反序列化的时候如果type不对则会
            // Process: com.zy.world, PID: 1739
            // java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter <set-?>
            // 	at com.zy.utils.data.Point$Builder.setType$utils_debug(Unknown Source:2)
            // 	at com.zy.utils.data.Point.toBuilder(Point.kt:81)
            // 	at com.zy.utils.CanvasUtils.buildPointList(CanvasUtils.kt:149)
            // 	at com.zy.list.layout.DiyLayoutEditFragment.onCreate$lambda-1(DiyLayoutEditFragment.kt:67)
            // 	at com.zy.list.layout.DiyLayoutEditFragment.$r8$lambda$OU62HDMW-MjkoNQYGVVAf6nPFD4(Unknown Source:0)
            // 	at com.zy.list.layout.DiyLayoutEditFragment$$ExternalSyntheticLambda0.onChanged(Unknown Source:4)
            // 	at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
            // 	at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
            // 	at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
            // 	at androidx.lifecycle.LiveData$1.run(LiveData.java:93)
            // 	at android.os.Handler.handleCallback(Handler.java:900)
            // 	at android.os.Handler.dispatchMessage(Handler.java:103)
            // 	at android.os.Looper.loop(Looper.java:219)
            // 	at android.app.ActivityThread.main(ActivityThread.java:8673)
            // 	at java.lang.reflect.Method.invoke(Native Method)
            // 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
            // 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)
            if (this.type != null) {
                it.type = this.type
            }
            it.backgroundColor = this.backgroundColor
            it.degrees = this.degrees
            it.arrowType = this.arrowType
            it.vTextSize = this.vTextSize
        }
    }

    //实际node中心X
    val centerX: Float
        get() = originX * d + offX * percentage

    //实际node中心Y
    val centerY: Float
        get() = originY * d + offY * percentage

    fun setPercentage(percentage: Float) {
        this.percentage = percentage
    }

    fun updateOff(x: Float, y: Float) {
        offX = x
        offY = y
    }

    fun updateOff(x: Int, y: Int) {
        offX = (x * d).toFloat()
        offY = (y * d).toFloat()
    }

    fun setMarked() {
        mark = !mark
    }

    fun resetOff() {
        offX = 0f
        offY = 0f
        percentage = 1f
    }

    fun setPoint(x: Int, y: Int) {
        originX = x
        originY = y
    }

    fun exchangeIndex(point: Point?) {
        if (point == null) {
            return
        }
        val tmp = index
        index = point.index
        point.index = tmp
    }

    fun updateV(point: Point) {
        this.v = point.v
    }

    fun updateD(d: Int) {
        this.d = d
        this.per = (d / 2 - 5).toFloat()
    }

    fun draw(canvas: Canvas, paint: Paint, backgroundPaint: Paint) {
        canvas.save()
        canvas.rotate(degrees, centerX, centerY)

        //绘制背景
        if (circle) {
            drawCircle(canvas, backgroundPaint)
        } else {
            drawBackground(canvas, backgroundPaint)
        }
        //绘制内容
        drawV(canvas, paint)
        if (showIndex) {
            //绘制 下标
            drawIndex(canvas, paint)
        }

        canvas.restore()
    }

    protected open fun drawV(canvas: Canvas, paint: Paint) {
        paint.color = Color.RED
        if (vTextSize < 36) {
            paint.textSize = 72F
        } else {
            paint.textSize = vTextSize.toFloat()
        }
        drawTextCenter(canvas, paint, centerX, centerY, v)
    }

    private fun drawIndex(canvas: Canvas?, paint: Paint) {
        val old = paint.textSize
        paint.textSize = 24f
        drawTextCenter(canvas!!, paint, centerX + per, centerY + per, index.toString())
        paint.textSize = old
    }

    protected open fun drawBackground(canvas: Canvas, paint: Paint) {
        //drawRect(canvas, paint)
        drawRoundRectBox(canvas, paint)
    }

    //直角
    fun drawRect(canvas: Canvas, paint: Paint?) {
        val x = centerX
        val y = centerY
        canvas.drawRect(x - per, y - per, x + per, y + per, paint!!)
    }

    protected open fun drawCircle(canvas: Canvas, paint: Paint) {
        val x = centerX
        val y = centerY
        if (mark) {
            paint.color = Color.GREEN
        } else {
            paint.color = Color.BLUE
        }
        canvas.drawCircle(x, y, per, paint)
    }

    //带弧度
    private fun drawRoundRectBox(canvas: Canvas, paint: Paint) {
        val x = centerX
        val y = centerY
        if (mark) {
            paint.color = Color.GREEN
        } else {
            paint.color = Color.GRAY
        }
        canvas.drawRoundRect(x - per, y - per, x + per, y + per, per / 4, per / 4, paint)


        backgroundColor?.let {
            backgroundPaint.color = it
            val d = 2
            canvas.drawRoundRect(
                x - per + d,
                y - per + d,
                x + per - d,
                y + per - d,
                per / 4,
                per / 4,
                backgroundPaint
            )
        }
    }

    fun canMove(): Boolean {
        return canMove
    }

    fun isRange(event: MotionEvent): Boolean {
        val x = event.x.toInt()
        val y = event.y.toInt()
        val originX = centerX
        val originY = centerY
        return x >= originX - per && x <= originX + per && y >= originY - per && y <= originY + per
    }

    enum class Type(val title: String) {
        DEFAULT("默认"),

        //无边框
        SUB_SCRIPT("数字"), ASSIST("辅助"),

        //辅助线<左右箭头>
        LINE("线")
    }

    class Builder {
        internal var originX //原始x
                = 0
        internal var originY //原始Y
                = 0
        internal var v //数据
                : String? = null
        internal var per //长宽或者R
                = 0f

        internal var d //标准单位
                = 0
        internal var index //下标
                = 0
        internal var showIndex //是否显示下标
                = false
        internal var circle //方形和圆形
                = false

        internal var canMove = true // 能否移动

        internal var type: Type = Type.DEFAULT //样式

        internal var backgroundColor: Int? = null //颜色


        //方向-[0,360]
        internal var degrees: Float = 0F

        //箭头
        internal var arrowType: Int = 0

        //内容字体大小
        internal var vTextSize: Int = 72

        fun setOriginX(originX: Int): Builder {
            this.originX = originX
            return this
        }

        fun setShowIndex(showIndex: Boolean): Builder {
            this.showIndex = showIndex
            return this
        }

        fun setVTextSize(vTextSize: Int): Builder {
            this.vTextSize = vTextSize
            return this
        }

        fun setCircle(circle: Boolean): Builder {
            this.circle = circle
            return this
        }

        fun setDegrees(degrees: Float): Builder {
            this.degrees = degrees
            return this
        }


        fun setArrowType(arrowType: Int): Builder {
            this.arrowType = arrowType
            return this
        }

        fun setOriginY(originY: Int): Builder {
            this.originY = originY
            return this
        }

        fun setV(v: String?): Builder {
            this.v = v
            return this
        }

        fun setPer(per: Float): Builder {
            this.per = per
            return this
        }

        fun setD(d: Int): Builder {
            this.d = d
            return this
        }

        fun setIndex(index: Int): Builder {
            this.index = index
            return this
        }

        fun setCanMove(canMove: Boolean): Builder {
            this.canMove = canMove
            return this
        }


        fun setBackgroundColor(backgroundColor: Int?): Builder {
            this.backgroundColor = backgroundColor
            return this
        }

        fun build(): Point {
            return build(type)
        }

        fun build(type: Type): Point {
            this.type = type
            return when (type) {
                Type.LINE -> {
                    LinePoint(this)
                }
                Type.SUB_SCRIPT -> {
                    SubScriptPoint(this)
                }
                Type.ASSIST -> {
                    AssistPoint(this)
                }
                else -> {
                    Point(this)
                }
            }
        }
    }
}